package com.personalink.reasoning.processor;

import com.personalink.common.dto.ChatRequest;
import com.personalink.common.dto.ChatResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.ChatClient;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

/**
 * 医疗助手处理器
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class MedicalProcessor implements PersonaProcessor {
    
    private final ChatClient chatClient;
    
    private static final String PERSONA_ID = "medical-assistant";
    private static final String PERSONA_NAME = "医疗助手";
    
    private static final String SYSTEM_PROMPT = 
            "你是一位专业的医疗助手，具备丰富的医学知识和临床经验。" +
            "你的职责是：\n" +
            "1. 提供准确的医疗信息和健康建议\n" +
            "2. 帮助用户理解症状和可能的原因\n" +
            "3. 建议适当的治疗方案和预防措施\n" +
            "4. 强调严重症状需要及时就医\n" +
            "5. 保持专业、耐心和同理心\n\n" +
            "重要提醒：\n" +
            "- 你的建议仅供参考，不能替代专业医生的诊断\n" +
            "- 对于紧急或严重症状，必须建议立即就医\n" +
            "- 不提供具体的药物剂量建议\n" +
            "- 保护用户隐私，不泄露个人健康信息";
    
    private static final List<String> SUPPORTED_INPUT_TYPES = Arrays.asList(
            "text", "image", "mixed"
    );
    
    @Override
    public Mono<ChatResponse> processRequest(ChatRequest request) {
        long startTime = System.currentTimeMillis();
        
        return preprocessRequest(request)
                .flatMap(this::generateMedicalResponse)
                .flatMap(this::postprocessResponse)
                .doOnNext(response -> {
                    response.setProcessingTime(System.currentTimeMillis() - startTime);
                    log.info("医疗助手处理完成，响应ID: {}, 处理时间: {}ms", 
                            response.getResponseId(), response.getProcessingTime());
                });
    }
    
    @Override
    public Flux<ChatResponse> processRequestStream(ChatRequest request) {
        return preprocessRequest(request)
                .flatMapMany(this::generateMedicalResponseStream)
                .map(this::createStreamResponse)
                .doOnNext(response -> log.debug("医疗助手流式响应: {}", response.getResponseId()));
    }
    
    @Override
    public String getPersonaId() {
        return PERSONA_ID;
    }
    
    @Override
    public String getPersonaName() {
        return PERSONA_NAME;
    }
    
    @Override
    public boolean supportsInputType(String inputType) {
        return SUPPORTED_INPUT_TYPES.contains(inputType);
    }
    
    @Override
    public Mono<ChatRequest> preprocessRequest(ChatRequest request) {
        // 医疗相关的预处理
        String content = request.getContent();
        
        // 检测紧急关键词
        if (containsEmergencyKeywords(content)) {
            log.warn("检测到紧急医疗关键词，用户ID: {}", request.getUserId());
            request.setUrgent(true);
        }
        
        // 添加医疗免责声明提醒
        if (!content.contains("免责声明")) {
            String enhancedContent = content + "\n\n[请注意：以下建议仅供参考，如有严重症状请及时就医]";
            request.setContent(enhancedContent);
        }
        
        return Mono.just(request);
    }
    
    @Override
    public Mono<ChatResponse> postprocessResponse(ChatResponse response) {
        // 添加医疗免责声明
        String content = response.getContent();
        if (!content.contains("免责声明")) {
            content += "\n\n⚠️ 免责声明：以上建议仅供参考，不能替代专业医生的诊断和治疗。如有严重或持续症状，请及时就医。";
            response.setContent(content);
        }
        
        // 设置医疗相关的元数据
        response.getMetadata().put("disclaimer", true);
        response.getMetadata().put("medicalAdvice", true);
        
        return Mono.just(response);
    }
    
    /**
     * 生成医疗响应
     */
    private Mono<ChatResponse> generateMedicalResponse(ChatRequest request) {
        List<Message> messages = Arrays.asList(
                new SystemMessage(SYSTEM_PROMPT),
                new UserMessage(request.getContent())
        );
        
        Prompt prompt = new Prompt(messages);
        
        return Mono.fromCallable(() -> chatClient.call(prompt))
                .map(result -> {
                    ChatResponse response = createBaseResponse(request);
                    response.setContent(result.getResult().getOutput().getContent());
                    response.setResponseType("medical_advice");
                    
                    // 添加医疗相关元数据
                    response.getMetadata().put("confidence", extractConfidence(result));
                    response.getMetadata().put("medicalCategory", categorizeMedicalQuery(request.getContent()));
                    
                    return response;
                })
                .onErrorResume(error -> {
                    log.error("医疗响应生成失败", error);
                    return Mono.just(createErrorResponse(request, "医疗咨询服务暂时不可用，请稍后重试"));
                });
    }
    
    /**
     * 生成流式医疗响应
     */
    private Flux<String> generateMedicalResponseStream(ChatRequest request) {
        List<Message> messages = Arrays.asList(
                new SystemMessage(SYSTEM_PROMPT),
                new UserMessage(request.getContent())
        );
        
        Prompt prompt = new Prompt(messages);
        
        return Flux.fromStream(() -> chatClient.stream(prompt)
                .map(result -> result.getResult().getOutput().getContent()))
                .onErrorResume(error -> {
                    log.error("医疗流式响应生成失败", error);
                    return Flux.just("医疗咨询服务暂时不可用，请稍后重试。");
                });
    }
    
    /**
     * 创建基础响应对象
     */
    private ChatResponse createBaseResponse(ChatRequest request) {
        ChatResponse response = new ChatResponse();
        response.setResponseId(UUID.randomUUID().toString());
        response.setUserId(request.getUserId());
        response.setSessionId(request.getSessionId());
        response.setPersonaId(PERSONA_ID);
        response.setTimestamp(LocalDateTime.now());
        return response;
    }
    
    /**
     * 创建流式响应对象
     */
    private ChatResponse createStreamResponse(String content) {
        ChatResponse response = new ChatResponse();
        response.setResponseId(UUID.randomUUID().toString());
        response.setPersonaId(PERSONA_ID);
        response.setContent(content);
        response.setResponseType("medical_advice_stream");
        response.setTimestamp(LocalDateTime.now());
        return response;
    }
    
    /**
     * 创建错误响应
     */
    private ChatResponse createErrorResponse(ChatRequest request, String errorMessage) {
        ChatResponse response = createBaseResponse(request);
        response.setContent(errorMessage);
        response.setResponseType("error");
        return response;
    }
    
    /**
     * 检测紧急关键词
     */
    private boolean containsEmergencyKeywords(String content) {
        String[] emergencyKeywords = {
                "胸痛", "呼吸困难", "昏迷", "大出血", "中毒", "骨折", 
                "心脏病发作", "中风", "过敏反应", "高烧", "剧烈疼痛"
        };
        
        String lowerContent = content.toLowerCase();
        return Arrays.stream(emergencyKeywords)
                .anyMatch(keyword -> lowerContent.contains(keyword.toLowerCase()));
    }
    
    /**
     * 提取置信度
     */
    private double extractConfidence(Object result) {
        // 简单的置信度计算逻辑
        return 0.85; // 默认置信度
    }
    
    /**
     * 医疗查询分类
     */
    private String categorizeMedicalQuery(String content) {
        if (content.contains("症状") || content.contains("疼痛")) {
            return "symptom_inquiry";
        } else if (content.contains("药物") || content.contains("治疗")) {
            return "treatment_inquiry";
        } else if (content.contains("预防") || content.contains("保健")) {
            return "prevention_inquiry";
        } else {
            return "general_medical";
        }
    }
}